﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using hedefgrup.reports.renault.database;
using System.Web;

namespace hedefgrup.reports.common
{
    public abstract class Report_Abstract
    {
        private List<Filter> _Filters;

        public List<Filter> Filters
        {
            get
            {
                if (_Filters == null)
                {
                    LoadFilters();
                }
                return _Filters;
            }
        }

        private List<Criteria> _Criterias;

        public List<Criteria> Criterias
        {
            get
            {
                if (_Criterias == null)
                {
                    _Criterias = new List<Criteria>();
                }
                return _Criterias;
            }
        }

        public ReportContext Context;

        private const string currentReportSessionKey = "{EA328994-8D55-4279-9ED5-595C6DA52329}";

        public static Report_Abstract Current
        {
            get
            {
                return HttpContext.Current.Session[currentReportSessionKey] != null ? HttpContext.Current.Session[currentReportSessionKey] as Report_Abstract : null;
            }
            set
            {
                HttpContext.Current.Session[currentReportSessionKey] = value;
            }
        }

        public abstract ReportResult GenerateReport();

        public abstract string SortPrefix { get; }

        public abstract string DisplayName
        {
            get;
        }

        public virtual string DealerColumn
        {
            get
            {
                return GetCriteriaByName("Network") != null ? GetCriteriaByName("Network").Value == Criteria_Network.Network1 ? "BAYIIKUMULE" : "BAYII" : "BAYII";
            }
        }

        public virtual string AreaColumn
        {
            get
            {
                return GetCriteriaByName("Organization").Value == Criteria_Organization.Dacia ? "DACIA_BOLGE" : "BOLGE";
            }
        }

        public virtual bool CoordinatorsReported
        {
            get
            {
                return GetCriteriaByName("Organization").Value == Criteria_Organization.Dacia ? false : true;
            }
        }

        public virtual bool AreasReported
        {
            get
            {
                return true;
            }
        }

        protected virtual void SetCriteriaList()
        {
            Criterias.Add(new Criteria_Roll() { Context = Context });
            Criterias.Add(new Criteria_BeginMonth() { Context = Context });
            Criterias.Add(new Criteria_EndMonth() { Context = Context });
            Criterias.Add(new Criteria_Network() { Context = Context });
            Criterias.Add(new Criteria_Organization() { Context = Context });
        }

        private bool IsUserDealer
        {
            get
            {
                return Context != null && Context.User != null && Context.User.getAuthLevel() == "dealer";
            }
        }

        public bool HasTICAuth
        {
            get
            {
                return
                    Context != null &&
                    (
                        Context.CompatibleProjectName != Global.PROJECT_SATIS_SUREC ||
                        (
                            Context.User != null &&
                            new List<string>(Context.User.getProjects()).Contains("TIC")
                        )
                    );
            }
        }

        private void LoadFilters()
        {
            _Filters = new List<Filter>();

            bool isUserDealer = IsUserDealer;

            DataTable columnListData = db.query("SELECT * FROM " + Context.TableName + " WHERE 1 = 2");
            foreach (DataColumn column in columnListData.Columns)
            {
                if (isUserDealer)
                {
                    if (column.ColumnName == "BAYII" || column.ColumnName == "BAYIIKUMULE" || column.ColumnName == "KOORDINATOR" || column.ColumnName == "BOLGE" || column.ColumnName == "DACIA_BOLGE")
                    {
                        continue;
                    }
                }
                _Filters.Add(new Filter_DataColumn(column) { Context = Context });
            }
        }

        protected Report_Abstract()
        {
            Context = new ReportContext() { Report = this };

            SetCriteriaList();
        }

        public virtual Criteria GetCriteriaByName(string criteriaName)
        {
            foreach (Criteria criteria in Criterias)
            {
                if (criteria.Name == criteriaName)
                {
                    return criteria;
                }
            }
            return null;
        }

        public virtual Filter GetFilterByName(string filterName)
        {
            foreach (Filter filter in Filters)
            {
                if (filter.Name == filterName)
                {
                    return filter;
                }
            }
            return null;
        }

        public virtual Filter[] GetAppliedFilters()
        {
            List<Filter> appliedFilters = new List<Filter>();
            foreach (Filter filter in Filters)
            {
                if (filter.Values.Count > 0)
                {
                    appliedFilters.Add(filter);
                }
            }
            return appliedFilters.ToArray();
        }

        public virtual void ClearFilters()
        {
            foreach (Filter filter in Filters)
            {
                filter.Values.Clear();
            }
        }

        public virtual string GetSqlStatementFilter()
        {
            return GetSqlStatementFilter(Criterias.ToArray(), GetAppliedFilters());
        }

        public virtual string GetSqlStatementFilter(Criteria[] criterias)
        {
            return GetSqlStatementFilter(criterias, GetAppliedFilters());
        }

        public virtual string GetSqlStatementFilter(Filter[] filters)
        {
            return GetSqlStatementFilter(Criterias.ToArray(), filters);
        }

        public virtual string GetSqlStatementFilter(Criteria[] criterias, Filter[] filters)
        {
            StringBuilder filterBuilder = new StringBuilder();

            if (criterias.Length > 0 || filters.Length > 0)
            {
                filterBuilder.Append("WHERE ");

                int parameterOffset = 0;

                foreach (Filter criteria in criterias)
                {
                    string filter = criteria.ToSqlStatementFilter(ref parameterOffset);
                    if (!string.IsNullOrEmpty(filter))
                    {
                        filterBuilder.AppendFormat("{0} AND ", filter);
                    }
                }

                foreach (Filter appliedFilter in filters)
                {
                    string filter = appliedFilter.ToSqlStatementFilter(ref parameterOffset);
                    if (filter != null)
                    {
                        filterBuilder.AppendFormat("{0} AND ", filter);
                    }
                }

                if (!HasTICAuth)
                {
                    filterBuilder.Append("(MODELGRUP IS NULL OR (MODELGRUP IS NOT NULL AND MODELGRUP NOT LIKE '%Ticari%')) AND ");
                }

                filterBuilder.Length -= 4;
            }

            return filterBuilder.ToString();
        }

        public virtual object[] GetSqlStatementParameters()
        {
            return GetSqlStatementParameters(Criterias.ToArray(), GetAppliedFilters());
        }

        public virtual object[] GetSqlStatementParameters(Criteria[] criterias)
        {
            return GetSqlStatementParameters(criterias, GetAppliedFilters());
        }

        public virtual object[] GetSqlStatementParameters(Filter[] filters)
        {
            return GetSqlStatementParameters(Criterias.ToArray(), filters);
        }

        public virtual object[] GetSqlStatementParameters(Criteria[] criterias, Filter[] filters)
        {
            List<object> parameters = new List<object>();

            if (criterias.Length > 0)
            {
                foreach (Filter criteria in criterias)
                {
                    int parameterOffset = 0;
                    string filter = criteria.ToSqlStatementFilter(ref parameterOffset);
                    if (!string.IsNullOrEmpty(filter) && parameterOffset > 0)
                    {
                        parameters.Add(criteria.ToSqlStatementValue());
                    }
                }
            }

            if (filters.Length > 0)
            {
                foreach (Filter appliedFilter in filters)
                {
                    int parameterOffset = 0;
                    string filter = appliedFilter.ToSqlStatementFilter(ref parameterOffset);
                    if (!string.IsNullOrEmpty(filter) && parameterOffset > 0)
                    {
                        parameters.AddRange(appliedFilter.ToSqlStatementValues());
                    }
                }
            }

            return parameters.ToArray();
        }

        internal Tree GetDealer(string dealerCode)
        {
            Tree[] matches = Context.Organization.Select("TR/*(area)/*(coordinator)/" + dealerCode);

            if (matches.Length == 0)
            {
                matches = Context.Organization.Select("TR/*(area)/*(coordinator)/*/" + dealerCode);

                if (matches.Length == 0)
                {
                    matches = Context.Organization.Select("TR/*(area)/" + dealerCode);
                    if (matches.Length == 0)
                    {
                        matches = Context.Organization.Select("TR/*(area)/*/" + dealerCode);
                        if (matches.Length == 0)
                        {
                            matches = Context.Organization.Select("S-2/" + dealerCode);
                            if (matches.Length == 0)
                            {
                                matches = Context.Organization.Select("TR/" + dealerCode);
                            }
                        }
                    }
                }
            }

            return matches.Length > 0 ? matches[0] : null;
        }

        protected string GetDealerDisplayName(string dealerCode)
        {
            return dealerCode + " - " + GetDealerName(dealerCode);
        }

        protected string GetDealerName(string dealerCode)
        {
            Tree dealer = GetDealer(dealerCode);

            if (dealer != null)
            {
                return dealer.Text;
            }
            else
            {
                return "";
            }
        }

        public virtual bool SupportsProject(string projectName)
        {
            return projectName == Global.PROJECT_QVN2013;
        }

        public virtual bool Authorized
        {
            get
            {
                return Context.User != null ? true : false;
            }
        }

        public virtual string GetAuthLevel()
        {
            return Context.User != null ? Context.User.getAuthLevel() : null;
        }

        private int maxYearForYearlyTotal = -1;
        protected int GetMaxYearForYearlyTotal()
        {
            if (maxYearForYearlyTotal == -1)
            {
                maxYearForYearlyTotal = Convert.ToInt32(db.query("SELECT MAX(YIL) FROM " + Context.TableName + " (NOLOCK)").Rows[0][0]);
            }
            return maxYearForYearlyTotal;
        }
    }
}
